package com.ncloud.act.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.ncloud.common.exception.UserException;
import com.ncloud.param.service.SequenceService;
import com.ncloud.act.entity.AccessLog;
import com.ncloud.act.entity.AccountDeposit;
import com.ncloud.act.entity.Bill;
import com.ncloud.act.entity.PayLog;
import com.ncloud.act.entity.PaymentDeposit;
import com.ncloud.act.entity.WriteOffLog;
import com.ncloud.act.mapper.AccessLogMapper;
import com.ncloud.act.mapper.AccountDepositMapper;
import com.ncloud.act.mapper.BillMapper;
import com.ncloud.act.mapper.PayLogMapper;
import com.ncloud.act.mapper.PaymentDepositMapper;
import com.ncloud.act.mapper.WriteOffLogMapper;

@Service
public class PayFeeTransServiceImpl{
	@Resource
	private PayLogMapper payLogMapper;
	@Resource
	private AccessLogMapper accessLogMapper;
	@Resource
	private AccountDepositMapper accountDepositMapper;
	@Resource
	private BillMapper billMapper;
	@Resource
	private WriteOffLogMapper writeOffLogMapper;
	@Resource
	private PaymentDepositMapper paymentDepositMapper;
	@Reference
	private SequenceService sequenceService;
	@Transactional(propagation=Propagation.REQUIRED)
	public JSONObject payFee(JSONObject json) throws ParseException{
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
		Date endDate = df.parse("2050-12-31 23:59:59");
		Long acct_id           =0l;
		Integer channel_id        =15000;
		Integer payment_id        =16000;
		Integer pay_fee_mode_code =0;
		Integer payment_op        =0;
		Long recv_fee          =0l;
		Long recv_user_id      =0l;
		String outer_trade_id    ="";
		String outer_pay_no      ="";
		String remark      ="";
		if(json.containsKey("acct_id"))
		{
			acct_id=json.getLong("acct_id");
		}else{
			throw new UserException("4000", "没有账户编码");
		}
		if(json.containsKey("channel_id"))
		{
			channel_id=json.getInteger("channel_id");
		}else{
			channel_id=15000;
		}
		if(json.containsKey("payment_id"))
		{
			payment_id=json.getInteger("payment_id");
		}else{
			throw new UserException("4000", "没有payment_id");
		}
		if(json.containsKey("pay_fee_mode_code"))
		{
			pay_fee_mode_code=json.getInteger("pay_fee_mode_code");
		}else{
			throw new UserException("4000", "没有pay_fee_mode_code");
		}
		if(json.containsKey("payment_op"))
		{
			payment_op=json.getInteger("payment_op");
		}else{
			payment_op=17000;
		}
		if(json.containsKey("recv_fee"))
		{
			recv_fee=json.getLong("recv_fee");
		}else{
			throw new UserException("4000", "没有缴费金额");
		}
		if(json.containsKey("userID"))
		{
			recv_user_id=json.getLong("userID");
		}
		if(json.containsKey("outer_trade_id"))
		{
			outer_trade_id=json.getString("outer_trade_id");
		}
		if(json.containsKey("outer_pay_no"))
		{
			outer_pay_no=json.getString("outer_pay_no");
		}
		if(json.containsKey("remark"))
		{
			remark=json.getString("remark");
		}
		Integer depositCode =0;
		List<PaymentDeposit> paymentDeposits=paymentDepositMapper.getPaymentDepositByPaymentID(payment_id.toString(), pay_fee_mode_code.toString());
		if(paymentDeposits.size()>0)
		{
			depositCode=paymentDeposits.get(0).getDeposit_code();
		}else{
			throw new UserException("4000", "没有配置bs_d_payment_deposit表信息");
		}
		Long acctBalanceID=0l;
		Long oldBalance = 0l;
		Long oldInvoiceFee = 0l;
		boolean depositExists = false;
		List<AccountDeposit> accountDeposits = accountDepositMapper.getAccountDepositByAcctID(acct_id);
		if(null!=accountDeposits&&accountDeposits.size()>0)
		{
			for(int i = 0; i < accountDeposits.size(); i++){
				AccountDeposit smap = accountDeposits.get(i);
				if(depositCode.equals(smap.getDeposit_code()))
				{
					acctBalanceID= smap.getAcct_balance_id();
					oldBalance=smap.getDeposit_money();
					oldInvoiceFee=smap.getInvoice_money();
					depositExists = true;
					break;
				}
			}
		}
		JSONObject param = new JSONObject();
		param.put("seqName", "charge_id");
		Long chargeID=sequenceService.getSequence(param);
		if(!depositExists)
		{
			param.put("seqName", "acct_balance_id");
			acctBalanceID=sequenceService.getSequence(param);
		}
		//paylog表数据组织
		PayLog payLog=new PayLog();
		payLog.setCharge_id(chargeID);
		payLog.setAcct_id(acct_id);
		payLog.setChannel_id(channel_id);
		payLog.setPayment_id(payment_id);
		payLog.setPay_fee_mode_code(pay_fee_mode_code);
		payLog.setPayment_op(payment_op);
		payLog.setRecv_fee(recv_fee);
		payLog.setRecv_user_id(recv_user_id);
		payLog.setRecv_time(new Date());
		payLog.setOuter_trade_id(outer_trade_id);
		payLog.setOuter_pay_no(outer_pay_no);
		//payLog.setProject_id(project_id);
		//payLog.setContract_inst_id(contract_inst_id);
		payLog.setCancel_tag("0");
		payLog.setCancel_user_id("");
		//payLog.setCancel_time("");
		payLog.setCancel_charge_id(0l);
		payLog.setRsrv_fee1(0l);
		payLog.setRsrv_info1("");
		payLog.setRemark(remark);
		//AccountDeposit表数据组织
		AccountDeposit accountDeposit=new AccountDeposit();
		if(depositExists)
		{
			accountDeposit.setAcct_balance_id(acctBalanceID);
			accountDeposit.setDeposit_money(oldBalance+recv_fee);
			accountDeposit.setInvoice_money(oldInvoiceFee+recv_fee);
			accountDeposit.setUpdate_time(new Date());
			accountDeposit.setUpdate_user_id(recv_user_id);
		}else{
			accountDeposit.setAcct_balance_id(acctBalanceID);
			accountDeposit.setAcct_id(acct_id);
			accountDeposit.setDeposit_code(depositCode);
			accountDeposit.setDeposit_money(recv_fee);
			accountDeposit.setInit_money(recv_fee);
			accountDeposit.setInvoice_money(recv_fee);
			accountDeposit.setPrint_money(0l);
			accountDeposit.setBegin_time(new Date());
			accountDeposit.setEnd_time(endDate);
			accountDeposit.setValid_tag(1);
			accountDeposit.setFreeze_money(0l);
			accountDeposit.setProject_id(0l);
			accountDeposit.setContract_inst_id(0l);
			accountDeposit.setUpdate_time(new Date());
			accountDeposit.setUpdate_user_id(recv_user_id);
			accountDeposit.setRsrv_money1(0l);
			accountDeposit.setRsrv_info1("");
			accountDeposit.setRemark("");
		}
		//AccessLog表数据组织
		AccessLog accessLog=new AccessLog();
		param.put("seqName", "access_id");
		Long accessID=sequenceService.getSequence(param);
		accessLog.setAccess_id(accessID);
		accessLog.setCharge_id(chargeID);
		accessLog.setAcct_id(acct_id);
		accessLog.setAcct_balance_id(acctBalanceID);
		accessLog.setDeposit_code(depositCode);
		accessLog.setOld_balance(oldBalance);
		accessLog.setMoney(recv_fee);
		accessLog.setNew_balance(oldBalance+recv_fee);
		accessLog.setAccess_tag(recv_fee>=0?"0":"1");
		accessLog.setRecv_time(new Date());
		accessLog.setRecv_user_id(recv_user_id);
		accessLog.setCancel_tag("0");
		//accessLog.setCancel_time("");
		accessLog.setCancel_user_id("");
		accessLog.setRemark("");
		payLogMapper.insertPayLog(payLog);
		if(depositExists)
		{
			accountDepositMapper.updateAccountDeposit(accountDeposit);
		}else{
			accountDepositMapper.insertAccountDeposit(accountDeposit);
		}
		accessLogMapper.insertAccessLog(accessLog);
		//JSONArray results=JSON.parseArray(JSON.toJSONString(payLog));
		json.put("charge_id",chargeID);
		//销帐
		this.writeOffFee(json);
		return json;
	}
	public JSONObject writeOffFee(JSONObject json) {
		Long acct_id=0l;
		if(json.containsKey("acct_id"))
		{
			acct_id=json.getLong("acct_id");
		}else{
			throw new UserException("4000", "没有账户编码");
		}
		Long recv_user_id=0l;
		if(json.containsKey("userID"))
		{
			recv_user_id=json.getLong("userID");
		}else{
			throw new UserException("4000", "没有登录帐号");
		}
		Long charge_id=0l;
		if(json.containsKey("charge_id"))
		{
			charge_id=json.getLong("charge_id");
		}else{
			throw new UserException("4000", "没有缴费流水");
		}
		List<Bill> bills = billMapper.getBillByAcctID(acct_id);
		if(bills==null || bills.size()==0){
			return null;
		}
		List<AccountDeposit> accountDeposits = accountDepositMapper.getAccountDepositByAcctID(acct_id);
		if(accountDeposits==null || accountDeposits.size()==0){
			return null;
		}
		for(int i=0;i<accountDeposits.size();i++)
		{
			AccountDeposit accountDeposit = accountDeposits.get(i);
			Long oldDepositMoney=accountDeposit.getDeposit_money();
			Long newDepositMoney=accountDeposit.getDeposit_money();
			for(int j=0;j<bills.size();j++)
			{
				if(newDepositMoney==0){
					break;
				}
				Bill bill = bills.get(j);
				if(bill.getBalance()>0)
				{
					Long oldBillBalance=bill.getBalance();
					Long writeOffMoney=(newDepositMoney>oldBillBalance)?oldBillBalance:newDepositMoney;
					Long newBillBalance=oldBillBalance-writeOffMoney;
					bill.setBalance(newBillBalance);
					String billPayTag="0";
					if(newBillBalance==0){
						billPayTag="2";
					}else{
						billPayTag="1";
					}
					bill.setBill_pay_tag(billPayTag);
					bill.setUpdate_time(new Date());
					bill.setUpdate_user_id(recv_user_id);
					
					Long writeoffID=sequenceService.getSequence("writeoff_id");
					WriteOffLog writeOffLog=new WriteOffLog();
					writeOffLog.setWriteoff_id(writeoffID);
					writeOffLog.setCharge_id(charge_id);
					writeOffLog.setAcct_id(bill.getAcct_id());
					writeOffLog.setCycle_id(bill.getCycle_id());
					writeOffLog.setBill_id(bill.getBill_id());
					writeOffLog.setNode_id(0l);
					writeOffLog.setItem_code(0);
					writeOffLog.setDeposit_code(accountDeposit.getDeposit_code());
					writeOffLog.setAcct_balance_id(accountDeposit.getAcct_balance_id());
					writeOffLog.setWriteoff_fee(writeOffMoney);
					writeOffLog.setFee(bill.getFee());
					writeOffLog.setOld_balance(oldBillBalance);
					writeOffLog.setNew_balance(newBillBalance);
					writeOffLog.setWriteoff_late_balance(0l);
					//writeOffLog.setLatecal_time("");
					writeOffLog.setOld_paytag(bill.getBill_pay_tag());
					
					writeOffLog.setNew_paytag(billPayTag);
					writeOffLog.setOperate_time(new Date());
					writeOffLog.setCancel_tag("0");
					writeOffLog.setRemark("");
					writeOffLogMapper.insertWriteOffLog(writeOffLog);
					billMapper.updateBill(bill);
					//==========================================================
					AccessLog accessLog=new AccessLog();
					Long accessID=sequenceService.getSequence("access_id");
					accessLog.setAccess_id(accessID);
					accessLog.setCharge_id(charge_id);
					accessLog.setAcct_id(acct_id);
					accessLog.setAcct_balance_id(accountDeposit.getAcct_balance_id());
					accessLog.setDeposit_code(accountDeposit.getDeposit_code());
					accessLog.setOld_balance(newDepositMoney);
					newDepositMoney=newDepositMoney-writeOffMoney;
					accessLog.setMoney(-writeOffMoney);
					accessLog.setNew_balance(newDepositMoney);
					accessLog.setAccess_tag((newDepositMoney-oldDepositMoney)>=0?"0":"1");
					accessLog.setRecv_time(new Date());
					accessLog.setRecv_user_id(recv_user_id);
					accessLog.setCancel_tag("0");
					//accessLog.setCancel_time("");
					accessLog.setCancel_user_id("");
					accessLog.setRemark("");
					accessLogMapper.insertAccessLog(accessLog);
				}
			}
			accountDeposit.setDeposit_money(newDepositMoney);
			accountDeposit.setUpdate_time(new Date());
			accountDeposit.setUpdate_user_id(recv_user_id);
			accountDepositMapper.updateAccountDeposit(accountDeposit);
		}
		return json;
	}
}
